/*********************************************************
*Copyright (c) 2009 Rob Groves. All Rights in Pw
*@des: seesion网络链接
*@name: seesion.cpp
*@author: zhognsx
*@time: 2015-11-16
*********************************************************/

#include "session.h"
//#include <boost/lexical_cast.hpp>
boost::detail::atomic_count session::m_last_id(0);

//#include "log4cplus/logger.h"
//#include "log4cplus/loggingmacros.h"

//using namespace log4cplus;
//extern log4cplus::Logger logFile1 = log4cplus::Logger::getInstance("logFile1");

//#include "../dll/include/StaticLogger.h"
//extern CStaticLogger logger;


session::session(boost::asio::io_service& ios) :
	io_service_(ios), socket_(ios),m_timer(ios)
{
	m_id = ++session::m_last_id;
	state = 0;
	read_buf_ = boost::shared_ptr<message>(new message());
}

session::~session()
{
	//async_close();

	//write_bufs_.clear();
}

std::string session::get_client_info()
{
	std::string szInfo = "客服端[";
	szInfo += address;
	szInfo += ":";
	szInfo += m_id; //boost::lexical_cast<std::string>(m_id);
	szInfo += "]";
	return szInfo;
}

boost::asio::ip::tcp::socket& session::socket()
{
	return socket_;
}

//30秒超时链接
bool session::is_timeout()
{
	std::time_t now;
	std::time(&now);
	return now - m_last_op_time > 15;
}


void session::start()
{
	//连接成功, 调用读取
	//socket_.set_option(boost::asio::ip::tcp::acceptor::linger(true, 0));
	//socket_.set_option(boost::asio::socket_base::keep_alive(true));
	read_buf_->reset(); //重复利用缓存
	std::time(&m_last_op_time);

	//读取数据报头 
	boost::asio::async_read(socket_,
		boost::asio::buffer(read_buf_->header(), read_buf_->header_len()),
		boost::bind(&session::handle_read_header, this, _1, _2));
}

void session::write(const char* data, int length)
{
	message_ptr mm(new message());
	mm->encode_data(data, length);

	std::time(&m_last_op_time);
	//异步写
	async_write(mm);
}

void session::async_write(boost::shared_ptr<message> msg)
{
	//将消息主动投递给io_service  
	io_service_.post(boost::bind(&session::do_write, this, msg));
}

void session::async_close()
{
	if (close_conn_callback){
		close_conn_callback(m_id);
	}
	//这个close函数是客户端要主动终止时调用  do_close函数是从服务器端  
	io_service_.post(boost::bind(&session::handle_close, shared_from_this()));
	//socket_.shutdown(boost::asio::socket_base::shutdown_both, boost::system::error_code());
	//1秒后调用handle_close 实际关闭socket
	//m_timer.expires_from_now(boost::posix_time::seconds(1));
    //m_timer.async_wait(boost::bind(&session::handle_close,shared_from_this(),
	//		boost::asio::placeholders::error));
	//io_service_.post(boost::bind(&session::do_close, this));
}

void session::do_write(boost::shared_ptr<message> msg)
{
	bool write_in_progress = !write_bufs_.empty(); //空的话变量为false  
	write_bufs_.push_back(msg); //把要写的数据push至写队列  
	if (!write_in_progress)//队列初始为空 push一个msg后就有一个元素了  
	{
		boost::shared_ptr<message> buf = write_bufs_.front();
		// 
		boost::asio::async_write(socket_, boost::asio::buffer(buf->data(), buf->length()),
			boost::bind(&session::handle_write, this, _1));
	}
}

//第一个消息单独处理，剩下的才更好操作  
void session::handle_write(const boost::system::error_code& ec)
{
	if (!ec){
		write_bufs_.pop_front();//刚才处理完一个数据 所以要pop一个  
		if (!write_bufs_.empty())
		{
			//循环处理剩余的消息 
			boost::shared_ptr<message> buf = write_bufs_.front();
			// 
			boost::asio::async_write(socket_, boost::asio::buffer(buf->data(), buf->length()),
				boost::bind(&session::handle_write, this, _1));
		}
	}
	else{
		//boost::shared_ptr<session> pSession = this->shared_from_this();
		errstr = ec.message();
		//logger->Error("session[%d], 写数据异常：[%s]", m_id, errstr.c_str());
		//LOG4CPLUS_INFO(logFile1, errstr);
	}
}

void session::handle_read_header(const boost::system::error_code& ec, int bytes_)
{
	//分别处理数据报头和数据部分  
	if (!ec) {
		//处理数据头,获取body数据长度
		if (bytes_ == read_buf_->header_len() ){
			read_buf_->add_wlen(bytes_);
			int len = read_buf_->body_len() + bytes_;
			if (len > read_buf_->get_mlen())
			{
				read_buf_->relloc(len);
			}
			//异步读取指定长度hlen的body数据
			boost::asio::async_read(socket_, boost::asio::buffer(read_buf_->body(), read_buf_->body_len()),
				boost::bind(&session::handle_read_msg, this, _1, _2));
		}
		else{
			start();
		}
	}
	else  {
		errstr = ec.message();
		//logger->Error("session[%d], 读取数据头出现异常:[%s]", m_id, errstr.c_str());
		
		//boost::shared_ptr<session> pSession = this->shared_from_this();
		//LOG4CPLUS_INFO(logFile1, errstr);
	}
}

void session::handle_read_msg(const boost::system::error_code& ec, int bytes_)
{
	boost::shared_ptr<session> pSession = this->shared_from_this();
	if (!ec){
		if (bytes_ == read_buf_->body_len()){
			read_buf_->add_wlen(bytes_);
			//生成处理消息
			//boost::shared_ptr<message> msg(new message());
			//调用处理函数
			read_msg_callback(pSession, read_buf_);
		}
		//继续
		start();
	}
	else{
		errstr = ec.message();
		//logger->Error("session[%d], 读取完整数据出现异常:[%s]", m_id, errstr.c_str());
		//std::cout << "Error2: " << errstr << std::endl;
		//LOG4CPLUS_INFO(logFile1, errstr);
	}
}

void session::handle_close()
{
	//socket_.shutdown(boost::asio::socket_base::shutdown_both);
	try {
		socket_.shutdown(boost::asio::socket_base::shutdown_both);
		//boost::asio::socket_base::linger option(true, 0);
		//socket_.set_option(option);
		socket_.close();
	}
	catch (std::exception& e) {
		//LOG4CPLUS_INFO(logFile1, "关闭连接"+m_id);
		//logger->Error("session[%d], 关闭连接异常，[%s]", m_id, e.what());
	}
}

void session::setaddress(std::string ip, short sport)
{
	address = ip;
	port = sport;
}